package com.study.suanfa.zhan;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * @description: JiSuanQi  栈实现计算器
 * @date: 2020/11/30 17:42
 * @author: hcm
 * @version: 1.0
 */
public class JiSuanQi {

    public static void main(String[] args) {
        //计算表达式
        String expression = "33+200*6-2";
        //创建
        MyStack numStack = new MyStack(10);
        MyStack operStack = new MyStack(10);
        //定义相关变量
        int index = 0;
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';
        String pushNumber = "";
        /**
         * 循环扫描，可以使用增强for，这里换一种方式
         */
        while (true) {
            //依次得到每一个字符
            ch = expression.substring(index, index + 1).charAt(0);
            //判断操作符
            if (operFlag(ch)) {
                //判断符号栈是否为空
                if (operStack.nullFlag()) {
                    //入栈
                    operStack.pushStack(ch);

                } else {
                    //当前操作符优先级小于或者等于栈中元素，pop出两个数计算
                    //符号栈pop一个符号，用来计算，结果入数栈
                    if (priority(ch) <= priority(operStack.topStackData())) {
                        num1 = numStack.popStack();
                        num2 = numStack.popStack();
                        oper = operStack.popStack();
                        res = cal(num1, num2, oper);
                        //运算结果入数栈
                        numStack.pushStack(res);
                        operStack.pushStack(ch);
                    } else {
                        //当前操作符优先级大于栈中的优先级，直接入符号栈
                        operStack.pushStack(ch);
                    }
                }
            } else {
                //字符拼接
                pushNumber += ch;
                if (index == expression.length() - 1) {
                    numStack.pushStack(Integer.parseInt(pushNumber));
                } else {
                    //判断下一个字符是不是数字，如果是数字继续扫描
                    if (operFlag(expression.substring(index + 1, index + 2).charAt(0))) {
                        //如果后一位是运算符，入栈
                        numStack.pushStack(Integer.parseInt(pushNumber));
                        //入栈后清空
                        pushNumber = "";
                    }
                }

            }
            //index + 1并判断是否扫描到expression
            index++;
            if (index >= expression.length()) {
                break;
            }
        }

        //符号栈为空，计算结束
        while (true) {
            if (operStack.nullFlag()) {
                break;
            }
            num1 = numStack.popStack();
            num2 = numStack.popStack();
            oper = operStack.popStack();
            res = cal(num1, num2, oper);
            numStack.pushStack(res);
        }
        int res2 = numStack.popStack();
        System.out.printf("表达式%s = %d", expression, res2);


    }

    /**
     * 返回运算符的优先级
     */
    private static int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        } else if (oper == '+' || oper == '-') {
            return 0;
        }
        return -1;
    }

    /**
     * 判断是不是一个运算符
     */
    public static Boolean operFlag(char val) {
        return val == '+' || val == '-' || val == '*' || val == '/';
    }

    /**
     * 计算方法
     */
    public static int cal(int num1, int num2, int oper) {
        //存放计算结果
        int res = 0;
        switch (oper) {
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;

        }

        return res;
    }
}

/**
 * 数组实现栈
 */
class MyStack {
    /**
     * 最大容量
     */
    int maxSize;

    /**
     * 栈顶
     */
    int top = -1;

    /**
     * 底层数组
     */
    int[] arr;

    public MyStack(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }

    /**
     * 返回一个栈顶元素，不改变结构
     */
    public int topStackData() {
        return arr[top];
    }

    /**
     * 空判
     */
    public Boolean nullFlag() {
        if (top == -1) {
            return true;
        }
        return false;
    }

    /**
     * 溢出判
     */
    public Boolean fullFlag() {
        if (top == maxSize - 1) {
            return true;
        }
        return false;
    }

    /**
     * 入栈
     */
    public void pushStack(int data) {
        if (fullFlag()) {
            System.out.println("栈已满，无法压入元素");
            return;
        }
        top++;
        arr[top] = data;
    }

    /**
     * 出栈
     */
    public int popStack() {
        //空判
        if (nullFlag()) {
            throw new NullPointerException("空栈，无法在出栈");
        }
        int res = arr[top];
        arr[top] = 0;
        top--;
        return res;
    }

    /**
     * 显示数组元素
     */
    public void showArr() {
        System.out.println(Arrays.toString(arr));
    }
}

